package cn.ac.iscas.domain;

import cn.ac.iscas.base.enums.TaskStatus;
import cn.ac.iscas.service.task.TaskListener;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Author: 
 * @Description:
 * @Date: 2020/6/11
 */
//@Data
//@Builder
public class ParentTask {
    private String id;
    private Map<String, NodeTask> nodeTasks;
    //成功结束的NodeTask个数
    private AtomicInteger nodeTaskSuccCnt;
    private volatile TaskStatus parentTaskStatus;
    private TaskListener taskListener;

    public ParentTask(String id, Map<String, NodeTask> nodeTasks, AtomicInteger nodeTaskSuccCnt, TaskStatus parentTaskStatus, TaskListener taskListener) {
        this.id = id;
        this.nodeTasks = nodeTasks;
        this.nodeTaskSuccCnt = nodeTaskSuccCnt;
        this.parentTaskStatus = parentTaskStatus;
        this.taskListener = taskListener;
    }

    private ParentTask(Builder builder) {
        this.id = builder.id;
        this.nodeTasks = builder.nodeTasks;
        this.nodeTaskSuccCnt = builder.nodeTaskSuccCnt;
        this.parentTaskStatus = builder.parentTaskStatus;
        this.taskListener = builder.taskListener;
    }

    /**
     * @Author: 
     * @Description: 计算运行度
     * @Date: 2020/6/12
     * @Param:
     * @return:
     **/
    public double getProgress() {
        double fraction = (double) nodeTaskSuccCnt.get() / nodeTasks.size();
        return (double) Math.round(fraction * 100) / 100;
    }

    /**
     * @Author: 
     * @Description: 获取各Task状态
     * @Date: 2020/6/13
     * @Return:
     **/
    public List<TaskResult> getTasksStatus() {
        Collection<NodeTask> values = nodeTasks.values();
        return values.stream().map(nodeTask ->
                new TaskResult(nodeTask.getTaskId(), nodeTask.getTaskStatus(), nodeTask.getTakeTime()))
                .collect(Collectors.toList());
    }

    public NodeTask getNodeTask(String nodeTaskId) {
        return nodeTasks.get(nodeTaskId);
    }

    public int nodeTaskSuccess() {
        return nodeTaskSuccCnt.addAndGet(1);
    }

    public void nodeTaskFail() {
        this.parentTaskStatus = TaskStatus.fail;
    }

    public boolean isFail() {
        return parentTaskStatus == TaskStatus.fail;
    }

    /**
     * @Author: 
     * @Description: Task是否失败或完成
     * @Date: 2020/6/12
     * @Param:
     * @return:
     **/
    public boolean isFailOrFinish() {
        return nodeTaskSuccCnt.get() == nodeTasks.size() || parentTaskStatus == TaskStatus.fail;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Map<String, NodeTask> getNodeTasks() {
        return nodeTasks;
    }

    public void setNodeTasks(Map<String, NodeTask> nodeTasks) {
        this.nodeTasks = nodeTasks;
    }

    public AtomicInteger getNodeTaskSuccCnt() {
        return nodeTaskSuccCnt;
    }

    public void setNodeTaskSuccCnt(AtomicInteger nodeTaskSuccCnt) {
        this.nodeTaskSuccCnt = nodeTaskSuccCnt;
    }

    public TaskStatus getParentTaskStatus() {
        return parentTaskStatus;
    }

    public void setParentTaskStatus(TaskStatus parentTaskStatus) {
        this.parentTaskStatus = parentTaskStatus;
    }

    public TaskListener getTaskListener() {
        return taskListener;
    }

    public void setTaskListener(TaskListener taskListener) {
        this.taskListener = taskListener;
    }

//    @Override
//    public boolean equals(Object obj) {
//        if (obj == this) {
//            return true;
//        }
//        if (obj == null || obj.getClass() != getClass()) {
//            return false;
//        }
//        ParentTask other = (ParentTask)obj;
//        return java.util.Objects.equals(this.id, other.id)
//                && java.util.Objects.equals(this.nodeTasks, other.nodeTasks)
//                && java.util.Objects.equals(this.nodeTaskSuccCnt, other.nodeTaskSuccCnt)
//                && java.util.Objects.equals(this.parentTaskStatus, other.parentTaskStatus)
//                && java.util.Objects.equals(this.taskListener, other.taskListener);
//    }
//    @Override
//    public int hashCode() {
//        return Objects.hash(this.id, this.nodeTasks, this.nodeTaskSuccCnt);
//    }
//    @Override
//    public String toString() {
//        return "Settings{font="+this.font+",fontSize="+this.fontSize+"}";
//    }
    public static Builder builder() {
        return new Builder();
    }
    public static class Builder {
        String id;
        Map<String, NodeTask> nodeTasks;
        AtomicInteger nodeTaskSuccCnt;
        TaskListener taskListener;
        volatile TaskStatus parentTaskStatus;

        private Builder() {
        }

        public Builder id(String id) {
            this.id = id;
            return this;
        }

        public Builder nodeTasks(Map<String, NodeTask> nodeTasks) {
            this.nodeTasks = nodeTasks;
            return this;
        }

        public Builder nodeTaskSuccCnt(AtomicInteger nodeTaskSuccCnt) {
            this.nodeTaskSuccCnt = nodeTaskSuccCnt;
            return this;
        }

        public Builder taskListener(TaskListener taskListener) {
            this.taskListener = taskListener;
            return this;
        }

        public Builder parentTaskStatus(TaskStatus parentTaskStatus) {
            this.parentTaskStatus = parentTaskStatus;
            return this;
        }

        public ParentTask build() {
            return new ParentTask(this);
        }
    }
}
